<!DOCTYPE html>
<html lang="en"><head>
    <title>CZH-DEV BLOG</title>
    <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
    <meta content="utf-8" http-equiv="encoding">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="format-detection" content="telephone=no" />
    <meta name="theme-color" content="#000084" />
    <link rel="icon" href="https://czh-dev.gitee.io/czh-blog.gitee.io//favicon.ico">
    <link rel="canonical" href="https://czh-dev.gitee.io/czh-blog.gitee.io/">
    
    
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
    <div class="navbar-inner">
        <div class="container">
            <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"></button>
            <a class="brand" href="https://czh-dev.gitee.io/czh-blog.gitee.io/">CZH-DEV BLOG</a>
            <div class="nav-collapse collapse">
                <ul class="nav">
                    
                    
                        
                            <li>
                                <a href="/czh-blog.gitee.io/about/">
                                    
                                    <span>About</span>
                                </a>
                            </li>
                        
                    
                        
                            <li>
                                <a href="/czh-blog.gitee.io/post/">
                                    
                                    <span>All posts</span>
                                </a>
                            </li>
                        
                    
                        
                            <li>
                                <a href="/czh-blog.gitee.io/ebook/">
                                    
                                    <span>Resource</span>
                                </a>
                            </li>
                        
                    
                </ul>
            </div>
        </div>
    </div>
</nav><div id="content" class="container">
<div style="display: flex;">
  <div class="row-fluid navmargin">
    <div class="page-header">
      <h1>常见面试题（一） - Sat, Feb 11, 2023</h1>
    </div>
    <p class="lead"></p>
    <h2 id="springboot">SpringBoot</h2>
<h3 id="spring和spring-boot的区别">Spring和Spring Boot的区别</h3>
<p>Spring和Spring Boot基于<a href="https://so.csdn.net/so/search?q=IOC&amp;spm=1001.2101.3001.7020">IOC</a> AOP理念实现，Spring Boot集成了Spring。</p>
<p>Spring Boot就是Spring的完善和扩展，就是为我们便捷开发，方便测试和部署，提高效率而诞生的框架技术。</p>
<h3 id="spring-springmvc-springboot的区别">Spring SpringMVC SpringBoot的区别</h3>
<p><strong>Spring MVC和Spring Boot都属于Spring，Spring MVC 是基于Spring的一个 MVC 框架，而Spring Boot 是基于Spring的一套快速开发整合包</strong></p>
<h2 id="springmvc的工作原理">SpringMVC的工作原理</h2>
<p><img src="https://czh-pic.oss-cn-guangzhou.aliyuncs.com/202302111730537.png" alt="image-20221102081333285"></p>
<ol>
<li>首先用户点击某个请求路径，发起一个 HTTP request 请求，该请求会被提交到 DispatcherServlet（前端控制器）；</li>
<li>由 DispatcherServlet 请求一个或多个 HandlerMapping（处理器映射器），并返回一个执行链（HandlerExecutionChain）。</li>
<li>DispatcherServlet 将执行链返回的 Handler 信息发送给 HandlerAdapter（处理器适配器）；</li>
<li>HandlerAdapter 根据 Handler 信息找到并执行相应的 Handler（常称为 Controller）；</li>
<li>Handler 执行完毕后会返回给 HandlerAdapter 一个 ModelAndView 对象（Spring MVC的底层对象，包括 Model 数据模型和 View 视图信息）；</li>
<li>HandlerAdapter 接收到 ModelAndView 对象后，将其返回给 DispatcherServlet ；</li>
<li>DispatcherServlet 接收到 ModelAndView 对象后，会请求 ViewResolver（视图解析器）对视图进行解析；</li>
<li>ViewResolver 根据 View 信息匹配到相应的视图结果，并返回给 DispatcherServlet；</li>
<li>DispatcherServlet 接收到具体的 View 视图后，进行视图渲染，将 Model 中的模型数据填充到 View 视图中的 request 域，生成最终的 View（视图）；</li>
<li>视图负责将结果显示到浏览器（客户端）。</li>
</ol>
<p><strong>MVC的工作原理：</strong></p>
<ol>
<li>由客户端发起请求</li>
<li>服务端接收请求，并解析请求</li>
<li>根据解析出来的请求，找到对应的控制器，并执行控制器</li>
<li>控制器调用模型获取数据，并将数据传给视图</li>
<li>视图将数据渲染出来。</li>
</ol>
<h2 id="mybatis和ibatis的区别">mybatis和ibatis的区别</h2>
<ol>
<li>Mybatis实现了接口绑定，使用更加方便</li>
<li>对象关系映射的改进，效率更高</li>
<li>MyBatis采用功能强大的基于OGNL的表达式来消除其他元素</li>
</ol>
<h2 id="jdk和cglib动态代理的区别">JDK和CGlib动态代理的区别</h2>
<p>（1）<strong>JDK</strong>动态代理只能对<strong>实现</strong>了接口的类生成代理，而不能针对类
（2）<strong>CGLIB</strong>是针对类实现代理，主要是对指定的类生成一个子类，覆盖其中的方法
因为是<strong>继承</strong>，所以该类或方法最好不要声明成final</p>
<p>JDK动态代理只提供接口的代理，不支持类的代理。核心InvocationHandler接口和Proxy类，InvocationHandler 通过invoke()方法反射来调用目标类中的代码，动态地将横切逻辑和业务编织在一起；接着，Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对象。
<strong>如果代理类没有实现 InvocationHandler 接口，那么Spring AOP会选择使用CGLIB来动态代理目标类</strong>。CGLIB（Code Generation Library），是一个代码生成的类库，可以在运行时动态的生成指定类的一个子类对象，并覆盖其中特定方法并添加增强代码，从而实现AOP。CGLIB是通过继承的方式做的动态代理，因此如果某个类被标记为final，那么它是无法使用CGLIB做动态代理的。</p>
<h2 id="autowired和resource">@Autowired和@Resource</h2>
<p><strong>1. @Autowired（这个注解是属于spring的） 默认按类型装配</strong>，默认情况下必须要求依赖对象必须存在，如果要允许null值，可以设置它的required属性为false，如@Autowired(required=false) ，<code>如果我们想使用名称装配可以结合 **@Qualifier** 注解</code>进行使用，如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span>  <span style="color:#a6e22e">@Autowired</span><span style="color:#f92672">(</span>required <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">@Qualifier</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;baseDao&#34;</span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">private</span> BaseDao baseDao<span style="color:#f92672">;</span>
</span></span></code></pre></div><ul>
<li>@Autowired 实现：</li>
</ul>
<blockquote>
<p>注解驱动配置会向spring容器中注册Autowired注解的后置处理器（AutowiredAnnotationBeanPostProcessor）。
当 Spring 容器启动时，AutowiredAnnotationBeanPostProcessor 将扫描 Spring 容器中所有 Bean，当发现 Bean 中拥有 @Autowired 注释时就找到和其匹配（默认按类型匹配）的 Bean，并注入到对应的地方中去。</p>
</blockquote>
<p><strong>2. @Resource (JDK1.6开始支持的注解) 默认按照名称进行装配</strong>。名称可以通过name属性进行指定。也提供按照byType 注入。</p>
<blockquote>
<ul>
<li>如果没有指定name属性，当注解写在字段上时，默认取字段名，按照名称查找。</li>
<li>当注解标注在属性的setter方法上，即默认取属性名作为bean名称寻找依赖对象。</li>
<li>当找不到与名称匹配的bean时才按照类型进行装配。 但是需要注意的是，如果name属性一旦指定，就只会按照名称进行装配。</li>
</ul>
</blockquote>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span>  <span style="color:#a6e22e">@Resource</span><span style="color:#f92672">(</span>name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;baseDao&#34;</span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">private</span> BaseDao baseDao<span style="color:#f92672">;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">@Resource</span><span style="color:#f92672">(</span>type <span style="color:#f92672">=</span> BaseDao<span style="color:#f92672">.</span><span style="color:#a6e22e">class</span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">private</span> BaseDao baseDao2<span style="color:#f92672">;</span>
</span></span></code></pre></div><ul>
<li>@Resource装配顺序</li>
</ul>
<blockquote>
<ul>
<li>如果同时指定了name和type，则从Spring上下文中找到唯一匹配的bean进行装配，找不到则抛出异常</li>
<li>如果指定了name，则从上下文中查找名称（id）匹配的bean进行装配，找不到则抛出异常</li>
<li>如果指定了type，则从上下文中找到类型匹配的唯一bean进行装配，找不到或者找到多个，都会抛出异常</li>
<li>如果既没有指定name，又没有指定type，则自动按照byName方式进行装配；如果没有匹配，则回退为一个原始类型进行匹配，如果匹配则自动装配；</li>
</ul>
</blockquote>
<p><strong>3. @Autowired 和 @Resource 作用域不同</strong></p>
<blockquote>
<ul>
<li>@Autowired 可以作用在construct，field，setter方法（可以有多个参数，并且参数上可以使用@Qualifies进行标注）</li>
<li>@Resource 只可以使用在field，setter方法上（只能是单个单数的setter方法）</li>
</ul>
</blockquote>
<h2 id="集合类">集合类</h2>
<p>集合类的特点：提供一种存储空间可变的存储模型，存储的数据容量可随时发生改变</p>
<p>我了解的集合类主要分为三大类，主要是是List、Set还有Map，</p>
<h3 id="list">List</h3>
<p>首先是<strong>List</strong>是有序的，它的实现主要有<strong>ArrayList、LinkedList、Vector</strong>这是比较常见的，其实还有<strong>SymchronizedList</strong>，这是<strong>Collections</strong>中的一个静态内部类，和<strong>Vector</strong>一样是线程安全的，说到线程安全，其实并发包里面还有一个<strong>CopyOnWriterArrayList</strong>也是线程安全的。</p>
<ul>
<li><strong>ArrayList</strong>和<strong>Vector</strong>实现的接口是<strong>List</strong>，而<strong>LinkedList</strong>实现的接口是<strong>List</strong>和<strong>Queue</strong></li>
<li><strong>ArrayList</strong>和<strong>Vector</strong>底层都是数组，而<strong>LinkedList</strong>底层是一个双向链表，所以<strong>ArrayList</strong>的查询效率是要比<strong>LinkedList</strong>的效率要高的，而<strong>LinkedList</strong>的增删效率则要比<strong>ArrayList</strong>高</li>
<li>然后扩容的话<strong>ArrayList</strong>是扩容成原来的1.5倍，而Vector扩容则是2倍或者指定的容量，其实集合类的创建在《阿里开发手册》里面是推荐手动设置容量的，这样可以防止资源浪费，然后<strong>LinkedList</strong>是不需要扩容的</li>
</ul>
<blockquote>
<p><strong>ArrayList扩容：</strong></p>
<p>ArrayList默认的容量是10，当添加第11个元素时就会进行扩容，扩容成原来的基础上再加50%就是扩容后变成15</p>
</blockquote>
<h3 id="set">Set</h3>
<p>然后是Set，Set集合的特点就是无序和唯一</p>
<p>Set的具体实现有<strong>HashSet</strong>、<strong>LinkedHashSet</strong>、<strong>TreeSet</strong></p>
<ul>
<li>其中<strong>HashSet</strong>和<strong>LinkedHashSet</strong>都是基于哈希表实现的，<strong>TreeSet</strong>则是基于红黑树实现的</li>
<li>因为<strong>TreeSet</strong>底层是红黑树，所以它天然就是会排序的。但是我们说Set集合是无序的，但是<strong>TreeSet</strong>又是有序的，其实这是不冲突的。因为Set的无序说的是存进去和取出来的顺序是不一样的，就是说先插进去的不一定就在前面。而TreeSet中的元素按照大小排序是一种排序手段，和Set无序并不冲突。TreeSet想要排序只要定义一个比较器，然后在定义<strong>TreeSet</strong>的时候把这个比较器传进去就行了；或者是可以传入一个<strong>Comparable</strong>接口，当我们添加对象的时候就可以根据这个元素中实现的<strong>compareTo</strong>方法进行比较了</li>
<li>所以<strong>HashSet</strong>和<strong>LinkedHashSet</strong>是通过<strong>equals</strong>()和<strong>hashcode</strong>()方法进行比较的，而<strong>TreeSet</strong>是通过<strong>compare</strong>()和<strong>compareTo</strong>()来比较对象的</li>
<li><strong>HashSet</strong>和<strong>LinkedHashSet</strong>运行存储一个null的，但是<strong>TreeSet</strong>是不允许存储null的</li>
</ul>
<h3 id="map">Map</h3>
<p>map的特点就是他存放的是个键值对</p>
<p>map主要的实现有<strong>HashMap</strong>、<strong>LinkedHashMap</strong>这两个和HashSet、<strong>LinkedHashSet</strong>一样都是基于哈希表的，还有<strong>TreeMap</strong>跟<strong>TreeSet</strong>一样是基于红黑树，所以<strong>TreeMap</strong>是有序的，还有两个线程安全的map就是<strong>HashTable</strong>和<strong>ConcurrentHashMap</strong>，Collections包下同样有<strong>SynchronizedMap</strong>这样线程安全的map</p>
<ul>
<li>
<p>HashMap的底层数据结构在JDK1.8之前是数组+链表，JDK1.8之后是数组链表红黑树</p>
</li>
<li>
<p><strong>HashTable</strong>和<strong>ConcurrentHashMap</strong>还有<strong>SynchronizedMap</strong>都是线程安全的，但是<strong>HashTable</strong>和<strong>SynchronizedMap</strong>会锁住整个Map对象就是类似一个全局锁，但是<strong>ConcurrentHashMap</strong>属于是一个分段锁，不会锁住整个Map对象，只需要一个桶级锁</p>
</li>
<li>
<p>所以<strong>HashTable</strong>和<strong>SynchronizedMap</strong>一次只允许一个线程操作一个Map对象，而<strong>ConcurrentHashMap</strong>同时允许多个对象操作Map对象，并且<strong>ConcurrentHashMap</strong>读操作可以不加锁，但是前面两个读写都需要加锁，所以效率会比前面两个要高</p>
</li>
<li>
<p><strong>HashMap</strong>和<strong>LinkedHashMap</strong>，<strong>SynchronizedMap</strong>是最多可以存储一个null键和多个null值，<strong>TreeMap</strong>则是不允许存储null键的，因为一旦有null键它的<strong>compareTo()<strong>方法就会报空指针异常，然后</strong>ConcurrentHashMap</strong>和<strong>HashTable</strong>的键值都不允许为null</p>
</li>
</ul>
<blockquote>
<p><strong>HashMap：</strong></p>
<p>HashMap 的主干是一个 Entry 数组。Entry 是 HashMap 的基本组成单元，每一个 Entry 包含一个key-value 键值对。链表则是主要为了解决哈希冲突而存在的，如果定位到的数组位置不含链表（当前 entry 的 next 指向 null）,那么对于查找，添加等操作很快，仅需一次寻址即可；如果定位到的数组包含链表，对于添加操作，其时间复杂度为 O(n)，首先遍历链表，存在即覆盖，否则新增；对于查找操作来讲，仍需遍历链表，然后通过 key 对象的 equals 方法逐一比对查找。所以，性能考虑，HashMap 中的链表出现越少，性能才会越好</p>
<p>HashMap在JDK1.8之后的数据结构是数组+链表+红黑树。创建的时候默认容量是16，当往map里面put()元素的时候，会先计算出这个key的hash值，再用这个hash值与当前容量求模，算出在数组中的位置，如果这个位置没有其他元素就直接放在这里，如果数组上有其他元素就用equals()方法比较两个key，如果两个key相同就覆盖原来的元素，如果不相同就会以链表的形式通过尾插法添加到链表的末尾，其实这就是HashMap用来解决hash冲突的方法——链地址法，这只是正常情况。因为它的底层数据结构还有一个红黑数，所以还考虑是不是添加在了红黑树上，就是当链表的长度大于8并且map的容量大于64这个链表就会转成红黑树。除了添加元素，还有删除元素，当红黑树的节点小于6的时候才会从红黑树变回链表，之所以设为6而不是和和转成红黑树是的8主要是为了防止哈希震荡。</p>
<p><strong>HashMap扩容：</strong></p>
<p>HashMap的初始容量是16，当数组被使用容量超过12个时就会进行第一次扩容，这个扩容的临界点的计算在源码有一个结算公式就是 当前容量*负载因子（0.75），所以16*0.75=12,然后它将扩容成之前的一倍，也就是32，扩容之后所有元素将会重新计算hash值，重新根据hash值放到数组对对应的位置，然后下一次扩容也就是32*0.75=24之后进行第二次扩容，再变成32的一倍64，这个时候如果某个链表的长度大于8就会转为红黑树了，但是每次扩容都是很消耗资源的，所以推荐在创建集合的时候手动设置一个合适的长度（计算方法：要存放的数据/0.75+1，但是JDK后把结果再处理变成2的幂，比如算出来是10，JDK就会处理成16）</p>
</blockquote>
<h2 id="mysql优化">MySQL优化</h2>
<h4 id="需求和架构的优化">需求和架构的优化</h4>
<p>需求和硬件也有会影响</p>
<p>表设计（char 定长字符串，varchar不定长字符串）</p>
<p>一些不常修改或者经常修改但是可靠性不高的可以放在redis中</p>
<p>选择合适的数据库引擎（myisam、innodb、NDB、Archive、Merge。。。）</p>
<p><img src="https://czh-pic.oss-cn-guangzhou.aliyuncs.com/202302111730472.png" alt="image-20221016211944210"></p>
<h2 id="查询语句的优化">查询语句的优化</h2>
<ol>
<li>
<p><strong>七个子句的优化</strong></p>
<ul>
<li>
<p>select不要用 * 号，写具体的字段，字段大写（少了个内部转换的过程）</p>
</li>
<li>
<p>distance后面字段增加索引</p>
</li>
<li>
<p>from能用内存表就用内存表（可以提高sql语句type的级别到system）</p>
</li>
<li>
<p>避免在where子句使用 != 、or、not in</p>
</li>
<li>
<p>用between and，不用 &lt;=, &gt;=这种，between and跟in一样属于精确查找，不是范围查找</p>
</li>
<li>
<p>where要满足最左前缀原则</p>
</li>
<li>
<p>where、having的字段可以加索引</p>
</li>
<li>
<p>为join条件的匹配条件添加索引，连接条件数据的长度尽量短</p>
</li>
<li>
<p>增大join缓存区的大小（可以再mysql的配置文件my.ini中配置缓存区大小: 在[mysqld] 这个节点下配置: <code>join_buffer_size = 8M</code> ）</p>
</li>
<li>
<p>group by + 索引</p>
</li>
<li>
<p>order by 可以+ 索引 也可以增大sort_buffer_size 参数来增大缓存区；也可以通过增大max_length_for_sort_data属性来优化排序算法</p>
</li>
<li>
<p>不要再group by、order by后面用被驱动表的字段</p>
</li>
<li>
<p>limit 尽量不要用 起始行，长度 如limit 3,2，过滤时总行数比较多</p>
<p>应该用where id&gt;3 limit 2这种类型（过滤时总行数比较少）</p>
</li>
</ul>
<blockquote>
<p>**双路排序：**要读两遍，一次读完数据（排序的列和指针地址）排序完之后通过指针再回表里面再查一次最后返回结果，效率低一些，但是buffer缓存区的利用率高，因为放的是地址，不是数据</p>
<p><strong>单路排序</strong>：只读一次，这个不读指针，会把数据一起都过来，不需要再回去查一次，因此效率快，但是缓存区buffer利用率低</p>
<p>MySQL根据max_length_for_sort_data变量来确定使用哪种算法，默认值是1024字节，如果需要返回的列的总长度大于<strong>max_length_for_sort_data</strong>，使用第一种算法，否则使用第二种算法。</p>
</blockquote>
</li>
<li>
<p><strong>多表的优化</strong></p>
<ul>
<li>尽量使用主表的字段</li>
<li>子查询不会产生笛卡尔积，尽量子查询，不用多表，如果select中的字段是多张表，子查询解决不了，只能用多表连接</li>
<li>小结果集驱动大结果集（内连接(inner join)有优化器，可以自己选择哪个小表驱动大表，如果是left join以左边为驱动表）（<strong>可以不说</strong>：不过也不是小表驱动大表一定好，因为可以提高type级别）</li>
</ul>
</li>
<li>
<p><strong>索引的使用</strong></p>
<ul>
<li>单值索引和组合索引优先使用组合索引(多值索引的定义顺序要按照sql语句使用的频率排序)</li>
</ul>
</li>
<li>
<p>提高sql语句的type类型（涉及到explain执行计划）</p>
</li>
</ol>
<h4 id="数据库自身的优化">数据库自身的优化</h4>
<ul>
<li>分库分表分区</li>
<li>主从主备</li>
<li>读写分离</li>
<li>使用数据库中间件mycat</li>
</ul>
<h3 id="索引">索引</h3>
<h4 id="索引的利弊">索引的利弊</h4>
<p>1，索引的<strong>好处</strong>：
1，提高查询速度，减小了服务器需要扫描的数据量
2，如果排序的列是索引列，大大降低排序成本；
3，在分组操作中如果分组条件是索引列，也会提高效率；</p>
<p>2，索引的问题：索引需要额外的维护成本(比如增删改都会引发索引的变动（B+树要重新排列）)</p>
<h4 id="索引类型">索引类型</h4>
<p>普通索引：仅加速查询</p>
<p>唯一索引：加速查询 + 列值唯一（可以有null）</p>
<p>主键索引：加速查询 + 列值唯一（不可以有null）+ 表中只有一个</p>
<p>组合索引：多列值组成一个索引，专门用在组合搜索，它的效率大于索引合并</p>
<p>全文索引：对文本的内容进行分词，进行搜索（目前只有MyISAM引擎支持）</p>
<p>非空约束：不能为空</p>
<blockquote>
<p>innoDB主键索引效率&gt;myisam主键索引&gt;myisam辅助索引&gt;innodb辅助索引（这个要回表）</p>
<p>Innodb的主键索引：B+Tree+数据（聚集索引）</p>
<p>非聚集索引：</p>
<p>Innodb的辅助索引：B+Tree+主键+ <!-- raw HTML omitted -->B+Tree<!-- raw HTML omitted --> +数据</p>
<p>myisam的主键索引：B+Tree+地址+数据</p>
<p>myisam的辅助索引：B+Tree+地址+数据（之所以比主键慢是因为主键索引唯一）</p>
</blockquote>
<h4 id="创建索引的注意事项">创建索引的注意事项</h4>
<p>1，唯一性太差的字段不适合单独创建索引，即使频繁作为查询条件；（比如性别）     2，较频繁作为查询条件的字段应该创建索引；where、having子句中出现的字段
3，更新非常频繁的字段不适合创建索引；
4，不会出现在WHERE 子句中的字段不该创建索引                                           5，order by，group by 的字段也要加索引，因为B+树有顺序的                          6，选择索引选择性接近1的作为索引                                                               7，主键索引要选择与业务无关的自增字段，类型用bigint（或者雪花算法或者uuid（最后再选择这个，因为这个没有顺序））                                                           8，尽量少的定义索引，每个索引都是b+树                                                            9，小于2000行不做索引</p>
<h4 id="索引失效">索引失效</h4>
<ul>
<li>不满足最左前缀原则</li>
<li>or关键字可能导致索引失效</li>
<li>范围查询放在前面，容易引起索引失效</li>
<li>like关键字后面用%或  _ 开头</li>
<li>在条件中使用函数可能引起索引失效</li>
<li>条件中等号左边使用表达式也使用不了索引</li>
</ul>
<p><img src="https://czh-pic.oss-cn-guangzhou.aliyuncs.com/202302111731170.png" alt="image-20221017001932149"></p>
<h3 id="执行计划explain">执行计划——explain</h3>
<p>id  select_type  table  partitions(分区表)  <code>**type**</code>  possible_keys(可能使用的索引)  key(实际用的索引)  key_len(索引长度，越短效率越高)  ref  rows  filtered  Extra</p>
<h4 id="select_type查询类型">select_type(查询类型)</h4>
<p>simple、primary、union、dependent union、union result、subquery、dependent subquery、derived</p>
<ul>
<li>simple：简单SELECT(不使用UNION或子查询)</li>
<li>primary：最外面的SELECT</li>
<li>union：UNION中的第二个或后面的SELECT语句</li>
<li>dependent union：UNION中的第二个或后面的SELECT语句,取决于外面的查询</li>
<li>union result：UNION 的结果</li>
<li>subquery：子查询中的第一个SELECT</li>
<li>dependent subquery：子查询中的第一个SELECT,取决于外面的查询</li>
<li>derived：FROM子句的子查询</li>
</ul>
<h4 id="type"><strong>type</strong></h4>
<p>system、const、eq_ref、ref、ref_or_null、index_merge、range、index、all</p>
<ul>
<li>system：表中仅有一行(=系统表)。这是const 联接类型的一个特例。</li>
<li>const：表中最多有一个匹配行,它将在查询开始时被读取。因为仅有一行,在这行的列值可被优化器剩余部分认为是常数。const表很快,因为它们只读取一次!</li>
<li>eq_ref：类似ref，区别就在使用的索引是唯一索引，对于每个索引键值，表中只有一条记录匹配，简单来说，就是多表连接中使用主键索引或者 唯一索引 作为关联条件</li>
<li>ref：对于每个来自于前面的表的行组合,所有有匹配索引值的行都会从这张表中读取</li>
<li>ref_or_null：该联接类型如同ref,但是添加了MySQL可以专门搜索包含NULL值的行</li>
<li>index_merge：该联接类型表示使用了索引合并优化方法。</li>
<li>range：只检索给定范围的行,并且使用一个索引来选择行。</li>
<li>index：除了只有索引树被扫描外和ALL相同,。这通常比ALL快,因为索引文件通常比数据文件小。</li>
<li>all：对于每个来自于先前的表的行组合,就是进行了完整的表扫描。</li>
</ul>
<table>
<thead>
<tr>
<th>类型</th>
<th>含义</th>
</tr>
</thead>
<tbody>
<tr>
<td>system</td>
<td>内存表</td>
</tr>
<tr>
<td>const</td>
<td>与常数比较</td>
</tr>
<tr>
<td>eq_ref</td>
<td>字段=单值主键约束（利用innodb的主键索引）</td>
</tr>
<tr>
<td>ref</td>
<td>字段=一个不是主键的普通索引</td>
</tr>
<tr>
<td>ref_or_null</td>
<td>or 左右两边一个是索引一个是null</td>
</tr>
<tr>
<td>index_merge</td>
<td>定义了多个索引，索引会合并</td>
</tr>
<tr>
<td>range</td>
<td>范围查询，并且用了一个索引（in、between and不算范围）</td>
</tr>
<tr>
<td>index</td>
<td>扫描了整个索引</td>
</tr>
<tr>
<td>all</td>
<td>扫描了整张表</td>
</tr>
</tbody>
</table>
<h4 id="extra">extra</h4>
<p>主要关注<strong>Using temporary</strong>这个类型，表示使用了临时表</p>

    <h4><a href="https://czh-dev.gitee.io/czh-blog.gitee.io/">Back to Home</a></h4>
  </div>

  <div class="span3 bs-docs-sidebar" style="position:fixed;right: 40px;top: 50px;">
    <h1>catalogue</h1>
    <ul class="nav nav-list bs-docs-sidenav">
      <div class="toc-div">
        <nav id="TableOfContents">
  <ul>
    <li><a href="#springboot">SpringBoot</a>
      <ul>
        <li><a href="#spring和spring-boot的区别">Spring和Spring Boot的区别</a></li>
        <li><a href="#spring-springmvc-springboot的区别">Spring SpringMVC SpringBoot的区别</a></li>
      </ul>
    </li>
    <li><a href="#springmvc的工作原理">SpringMVC的工作原理</a></li>
    <li><a href="#mybatis和ibatis的区别">mybatis和ibatis的区别</a></li>
    <li><a href="#jdk和cglib动态代理的区别">JDK和CGlib动态代理的区别</a></li>
    <li><a href="#autowired和resource">@Autowired和@Resource</a></li>
    <li><a href="#集合类">集合类</a>
      <ul>
        <li><a href="#list">List</a></li>
        <li><a href="#set">Set</a></li>
        <li><a href="#map">Map</a></li>
      </ul>
    </li>
    <li><a href="#mysql优化">MySQL优化</a>
      <ul>
        <li></li>
      </ul>
    </li>
    <li><a href="#查询语句的优化">查询语句的优化</a>
      <ul>
        <li></li>
        <li><a href="#索引">索引</a></li>
        <li><a href="#执行计划explain">执行计划——explain</a></li>
      </ul>
    </li>
  </ul>
</nav>
      </div>
    </ul>
  </div>

</div>
<script src="https://cdn.jsdelivr.net/npm/gumshoejs@5.1.2/dist/gumshoe.min.js"></script>
<script>
  var spy = new Gumshoe('#TableOfContents a', {
    nested: true,
    nestedClass: 'active'
  });
</script>
<style>
   
  #TableOfContents li,
  #TableOfContents ul {
    list-style-type: none;
  }

  #TableOfContents ul {
    padding-left: 0px;
  }

  #TableOfContents li>a {
    display: block;
    padding: 4px 20px;
    font-size: 95%;
    color: #000000;
  }

  #TableOfContents li>a:hover,
  #TableOfContents li>a:focus {
    padding-left: 19px;
    color: #3A6bA5;
    text-decoration: none;
    background-color: transparent;
    border-left: 1px solid #3A6bA5;
  }

  #TableOfContents li.active>a,
  #TableOfContents li.active>a:hover,
  #TableOfContents li.active>a:focus {
    padding-left: 18px;
    font-weight: bold;
    color: #3A6bA5;
    background-color: transparent;
    border-left: 2px solid #3A6bA5;
  }

   
  #TableOfContents li>ul {
    padding-bottom: 10px;
  }

  #TableOfContents li li>a {
    padding-top: 1px;
    padding-bottom: 1px;
    padding-left: 30px;
    font-size: 14px;
    font-weight: normal;
  }

  #TableOfContents li li>a:hover,
  #TableOfContents li li>a:focus {
    padding-left: 29px;
  }

  #TableOfContents li li.active>a,
  #TableOfContents li li.active>a:hover,
  #TableOfContents li li.active>a:focus {
    padding-left: 28px;
    font-weight: 500;
  }

  #TableOfContents .nav-link.active+ul {
    display: block;
  }

  #TableOfContents li>ul {
    display: none;
  }

  #TableOfContents li.active>ul {
    display: inherit;
  }

  .toc-div {
    position: -webkit-sticky;
     
    position: sticky;
     
    top: 20px;
  }
</style>


        </div><footer class="container">
    <hr class="soften">
    <p>
    <a href="https://space.bilibili.com/1799809923">Love eating fried pork ribs</a> | 

&copy; 
<a href="http://jmf-portfolio.netlify.com" target="_blank">
    JM Fergeau
</a>
<span id="thisyear">2023</span>

    | My site


        | Built on <a href="//gohugo.io" target="_blank">Hugo</a>

</p>
    <p class="text-center">
        <a href="https://facebook.com">Facebook</a> 
        <a href="https://twitter.com">Twitter</a> 
        <a href="https://linkedin.com">Linkedin</a> 
        <a href="https://github.com">GitHub</a> 
        <a href="https://gitlab.com">GitLab</a>
    </p>
</footer>

</body><link rel="stylesheet" href="/czh-blog.gitee.io/css/bootstrap.css">
<link rel="stylesheet" href="/czh-blog.gitee.io/css/bootstrap-responsive.css">
<link rel="stylesheet" href="/czh-blog.gitee.io/css/style.css">

<script src="/czh-blog.gitee.io/js/jquery.js"></script>
<script src="/czh-blog.gitee.io/js/bootstrap-386.js"></script>
<script src="/czh-blog.gitee.io/js/bootstrap-transition.js"></script>
<script src="/czh-blog.gitee.io/js/bootstrap-alert.js"></script>
<script src="/czh-blog.gitee.io/js/bootstrap-modal.js"></script>
<script src="/czh-blog.gitee.io/js/bootstrap-dropdown.js"></script>
<script src="/czh-blog.gitee.io/js/bootstrap-scrollspy.js"></script>
<script src="/czh-blog.gitee.io/js/bootstrap-tab.js"></script>
<script src="/czh-blog.gitee.io/js/bootstrap-tooltip.js"></script>
<script src="/czh-blog.gitee.io/js/bootstrap-popover.js"></script>
<script src="/czh-blog.gitee.io/js/bootstrap-button.js"></script>
<script src="/czh-blog.gitee.io/js/bootstrap-collapse.js"></script>
<script src="/czh-blog.gitee.io/js/bootstrap-carousel.js"></script>
<script src="/czh-blog.gitee.io/js/bootstrap-typeahead.js"></script>
<script src="/czh-blog.gitee.io/js/bootstrap-affix.js"></script>
<script>
    _386 = { 
        fastLoad: false ,
        onePass: false , 
        speedFactor: 1 
    };

    
    function ThisYear() {
        document.getElementById('thisyear').innerHTML = new Date().getFullYear();
    };
</script>
</html>
